#include "mian_util.h"
#include "result.h"
#include "compress_gpu.h"
#include "compress_cpu.h"

#define BINARY (1)
#define DELTA (2)
#define GOLOMB32 (3)
#define GOLOMB8 (4)
int main(int argc, char* argv[])
{
	char* inFileName = argv[1];
	uint32 dataSize = atoi(argv[2]);
	uint32 choice = atoi(argv[3]);

	if(choice == BINARY) {
		// test binary encoding
		uint8* data = (uint8*)malloc(dataSize);
		uint8* data1 = (uint8*)malloc(dataSize);
		uint8* out = (uint8*)malloc( ceil((double)dataSize / 4.0));
		uint32 outSize;

		FILE* infile = fopen(inFileName, "rb");
		fread(data, 1, dataSize, infile);

		INIT_TIMER;
		START_TIMER;
		gpu_binary_encoding_test(data, dataSize, out);

		END_TIMER;
		PRINT_TIMER_SEC("binary coding gpu ");

		//check result
		cpu_binaryDecoding_2bit(out, data1, ceil((double)dataSize/4));
		for(uint32 i=0; i<dataSize; i++) {
			if(data[i] != data1[i]) {
				printf("i: %u, data: %u, data1: %u\n",i, data[i], data1[i]);
				break;
			}
		}

		//compare with cpu version
		uint64 bitSize_cpu;
		START_TIMER;
		cpu_binaryEncoding_2bit(data, out, dataSize, &outSize);	
		printf("out size cpu: %u\n", outSize);
		END_TIMER;
		PRINT_TIMER_SEC("binary coding cpu ");
		free(data);
		free(out);
		fclose(infile);
	}
	else if(choice == DELTA) {
		uint32* data = (uint32*)malloc(dataSize * sizeof(int));
		uint32* data1 = (uint32*)malloc(dataSize * sizeof(int));

		FILE* infile = fopen(inFileName, "rb");
		fread(data, sizeof(int), dataSize, infile);
		memcpy(data1, data, sizeof(int)*dataSize);

		INIT_TIMER;
		START_TIMER;
		gpu_delta_encoding_test(data, dataSize);
		END_TIMER;
		PRINT_TIMER_SEC("binary coding gpu ");

		//check result

		//compare with cpu version
		START_TIMER;
		cpu_delta_compress((int*)data, dataSize, 1);	
		END_TIMER;
		PRINT_TIMER_SEC("binary coding cpu ");
		free(data);
		fclose(infile);
	}
	else if(choice == GOLOMB32) {
		uint32* data = (uint32*)malloc(dataSize * sizeof(int));
		uint32* data1 = (uint32*)malloc(dataSize * sizeof(int));
		uint8* out = (uint8*)malloc(dataSize * sizeof(int));
		uint32 outBitSize;

		FILE* infile = fopen(inFileName, "rb");
		fread(data, sizeof(int), dataSize, infile);

		INIT_TIMER;
		START_TIMER;
		
		gpu_golomb_coding_test(data, dataSize, out, &outBitSize);
		END_TIMER;
		PRINT_TIMER_SEC("golomb coding gpu ");

		//check result
		golombDecode(out, data1, 32, outBitSize);
		cpu_delta_compress((int*)data, dataSize, 1);	
		for(uint32 i=0; i<dataSize; i++) {
			if(data[i] != data1[i]) {
				printf("data: %u, data1: %u\n", data[i], data1[i]);
			}
		}

		//compare with cpu version
		uint64 bitSize_cpu;
		START_TIMER;
		golombEncode(data, out, 32, dataSize, &bitSize_cpu);
		printf("bit size cpu: %u\n", bitSize_cpu);
		END_TIMER;
		PRINT_TIMER_SEC("golomb coding cpu ");

		free(data);
		free(data1);
		free(out);
		fclose(infile);

	}
	else if(choice == GOLOMB8) {
		uint8* data = (uint8*)malloc(dataSize);
		uint8* data1 = (uint8*)malloc(dataSize);
		uint8* out = (uint8*)malloc(dataSize * sizeof(int));
		uint32 outBitSize;

		FILE* infile = fopen(inFileName, "rb");
		fread(data, 1, dataSize, infile);

		INIT_TIMER;
		START_TIMER;
		
		gpu_golomb_coding_test(data, dataSize, out, &outBitSize);
		END_TIMER;
		PRINT_TIMER_SEC("golomb coding gpu ");

		//check result
		golombDecode(out, data1, 16, outBitSize);
		for(uint32 i=0; i<dataSize; i++) {
			if(data[i] != data1[i]) {
				printf("data: %u, data1: %u\n", data[i], data1[i]);
				break;
			}
		}

		//compare with cpu version
		uint64 bitSize_cpu;
		START_TIMER;
		golombEncode(data, out, 16, dataSize, &bitSize_cpu);
		printf("bit size cpu: %u\n", bitSize_cpu);
		END_TIMER;
		PRINT_TIMER_SEC("golomb coding cpu ");

		free(data);
		free(data1);
		free(out);
		fclose(infile);

	}


	return 0;
}

